package com.qf.index;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;

public class Country {
    /**
     * 获取（全写的）作者单位信息中的国家名称的主方法，第一次采用 ", " 切割提取国家，如果提取不到，再采用 " " 切割。主方法为：getCountry，输入的参数为C1或RP全写的单位信息，以及国家Map。
     * 贾新志 2024.12.03
     */

    public static void main(String[] args) throws SQLException {

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(format.format(new Date()) + " 程序开始了~~~");

        String guidelinesTable = "scholar_25_01.pm_ut_aid_info_1218_guidelines";
        String notC1SumTable = "scholar_25_01.not_c1_sum";
        String c1InfoCountryTable = "scholar_25_01.c1_info_country";

        // ① 整理没有国家的C1字段，整理好后就开始使用阿里通义进行规范国家名称了。整理好后下面的代码需要注掉。
        doNotC1Sum(guidelinesTable, "id", "C1`,`RP", notC1SumTable, c1InfoCountryTable);

        // ② 通过通义获取国家的名称，此部分主要分三种，一种看是否包含中国的省份，一种是看是否存在大学，如果存在优先通过大学来获取大学，若无再通过c1字符串来获取国家。跑此程序时上面的代码①应注掉。
//        tongYiGetCountry(notC1SumTable, "id", "info`,`sum`,`country`,`univ`,`univ_country");

        // ③ 获取各个国家出现的次数，用于判断各个国家的字符串。这个是用于测试，不用于实际的计算，主要查看通义翻译的效果以及后续如何应用通义的翻译。
//        getCountrySum(notC1SumTable, "id", "univ_country", notC1SumCountry);

        // ④ 使用指定的192个国家的标准名称，更新其表，并返回c1相对应的国家集合。isUpData更新时两个功能都执行，不是更新时，仅返回c1相对应的国家集合。
//        Map<String, List<String>> c1AndCountryListMap = use192Country(notC1SumTable, "id", "info`,`univ_country", true);
        // ⑤ 对原总表bibliometricPmTable的中文国家名这一字段进行更新，实现最终的功能目标。运行④⑤时，前面的三个①②③均应注掉。④是为⑤提供数据的，需要一块儿运行。
//        upDataCountry(bibliometricPmTable, "id", "sort_auth", c1AndCountryListMap);

        System.out.println(format.format(new Date()) + " 程序结束了~~~");

    }


    public static void doNotC1Sum(String guidelinesTable, String autoId, String field, String notC1SumTable, String c1InfoCountryTable) throws SQLException {
        // 使用老方法处理从c1字段内，没有提取出来的国家名称，并计算每个c1出现的次数后存表。
        Db.use().execute("truncate table " + c1InfoCountryTable);
        Map<String, String> countryMap = cList.getCountryMap();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        int onePageNum = 1000;
        Map<String, Integer> c1AndSumMap = new ConcurrentHashMap<>();
        int tableMax = Db.use().queryNumber("select max(" + autoId + ") from " + guidelinesTable).intValue();
        if (tableMax > 0) {
            Collection<Integer> tableList = new ArrayList<>();
            NumberUtil.appendRange(0, tableMax + onePageNum, onePageNum, tableList);
            tableList.parallelStream().forEach(startId -> {
                try {
                    List<Entity> tableData = Db.use().query("select `" + autoId + "`,`" + field + "` from " + guidelinesTable + " where " + autoId + " between " + startId + " and " + (startId + onePageNum - 1));
                    System.out.println("\033[31;1m" + format.format(new Date()) + " 读表现在开始：" + startId + " 表名：" + guidelinesTable + Utils.printMemoryStr() + "\033[0m");
                    for (Entity entry : tableData) {
                        List<En.C1Auth> c1AuthList = Utils.getC1List(entry.getStr("C1"));
                        List<En.C1Auth> rpAuthList = Utils.getRpList(entry.getStr("RP"));
                        insertTable(c1AuthList, countryMap, c1AndSumMap, c1InfoCountryTable);
                        insertTable(rpAuthList, countryMap, c1AndSumMap, c1InfoCountryTable);
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            });
        }
        Db.use().execute("truncate table " + notC1SumTable);
        c1AndSumMap.keySet().parallelStream().forEach(c1 -> {
            try {
                Db.use().insert(Entity.create(notC1SumTable).set("info", c1).set("sum", c1AndSumMap.get(c1)));
            } catch (SQLException e) {
                e.printStackTrace();
            }
        });
    }

    public static void insertTable(List<En.C1Auth> c1AuthList, Map<String, String> countryMap, Map<String, Integer> c1AndSumMap, String c1InfoCountryTable) {
        // 从C1作者信息中提取国家的名称，如果有则直接插表，如果无则记录到c1AndSumMap，后续需要人工处理后再使用。
        for (En.C1Auth c1Auth : c1AuthList) {
            String country = findCountry(c1Auth.getFull(), countryMap, ", ");
            if (country.isEmpty()) {
                country = findCountry(c1Auth.getFull(), countryMap, " ");
            }
            if (country.isEmpty()) {
                c1AndSumMap.compute(c1Auth.getFull(), (key, value) -> value != null ? (value + 1) : 1);
            } else {
                try {
                    Db.use().insert(Entity.create(c1InfoCountryTable).set("c1_info", c1Auth.getFull()).set("country", country));
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static String getCountry(String full, Map<String, String> countryMap, Set<String> chinaSet) {
        // 获取（全写的）作者单位信息中的国家名称的主方法，第一次采用 ", " 切割提取国家，如果提取不到，再采用 " " 切割。输入的参数为C1或RP全写的单位信息，以及国家Map。
        String country = findCountry(full, countryMap, ", ");
        country = country.isEmpty() ? findCountry(full, countryMap, ",") : country;
        country = country.isEmpty() ? findCountry(full, countryMap, " ") : country;
        if (country.isEmpty()) {
            if ((Pattern.compile(",[a-zA-Z]{2} [0-9]{5}$|, [a-zA-Z]{2} [0-9]{5}$").matcher(full).find())) {
                return "美国";
            }
        }
        if (country.isEmpty()) {
            for (String s : chinaSet) {
                if (full.contains(s)) {
                    return "中国";
                }
            }
        }
        return country;
    }

    public static String findCountry(String c1, Map<String, String> countryMap, String split) {
        // 从c1作者单位信息中提取国家的名称，采用的方法是，从长到短的方式，即长的匹配上了，短的就忽略了。
        String t = c1.toLowerCase();
        if (t.contains("united states of america")) {
            return "美国";
        }
        String[] c1Split = t.replace("；", split).replace("。", split).replace("： ", split).replace("， ", split).replace("; ", split).replace(". ", split).replace(": ", split).replace(", ", split).split(split);
        Map<String, Integer> map = new HashMap<>();
        for (String s : c1Split) {
            map.put(s, s.length());
        }
        Map<String, Integer> sortValueStrInt = Utils.mapSortValueStrInt(map);
        for (Map.Entry<String, Integer> entry : sortValueStrInt.entrySet()) {
            if (countryMap.containsKey(entry.getKey().trim())) {
                return countryMap.get(entry.getKey().trim());
            }
        }
        return "";
    }


}
